/**
 * 
 */
package kulstats.server;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import kulstats.CourseManager;
import kulstats.QuestionnaireManager;
import kulstats.Registry;
import kulstats.StatisticsDateType;
import kulstats.StatisticsManager;
import kulstats.User;
import kulstats.UserManager;

import com.google.visualization.datasource.DataSourceServlet;
import com.google.visualization.datasource.base.DataSourceException;
import com.google.visualization.datasource.base.TypeMismatchException;
import com.google.visualization.datasource.datatable.ColumnDescription;
import com.google.visualization.datasource.datatable.DataTable;
import com.google.visualization.datasource.datatable.value.ValueType;
import com.google.visualization.datasource.query.Query;

/**
 * @author steven
 *
 */
public class ChartDataSourceServlet extends DataSourceServlet {

	@Override
	protected boolean isRestrictedAccessMode() {
		return false;
	}
	
	/* (non-Javadoc)
	 * @see com.google.visualization.datasource.DataTableGenerator#generateDataTable(com.google.visualization.datasource.query.Query, javax.servlet.http.HttpServletRequest)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public DataTable generateDataTable(Query query, HttpServletRequest req)
			throws DataSourceException {
		
    	UserManager userManager = Registry.userManager();
    	User currentUser = userManager.getCurrentUser();
    	if(currentUser == null) {
    		//empty datatable, user not logged in
    		return new DataTable();
    	}
    	
    	StatisticsManager statisticsManager = Registry.statisticsManager();
    	QuestionnaireManager questionManager = Registry.questionnaireManager();
    	CourseManager courseManager = Registry.courseManager();
		String statType = req.getParameter("stat_type").toLowerCase();
		String statTime = req.getParameter("stat_time").toLowerCase();
		String statWhom = req.getParameter("stat_whom").toLowerCase();
		String statChar = req.getParameter("stat_char").toLowerCase();
		String statCrse = req.getParameter("stat_crse");
		int statOffs = 0;
		if (req.getParameter("stat_offs") != null && !req.getParameter("stat_offs").equals(""))
    	statOffs  = Integer.parseInt(req.getParameter("stat_offs"));
		System.out.println("ChartData: " + statType + " " + statTime + " " +  statWhom + " " + statChar + " " + statOffs);

		DataTable data = new DataTable();

		List<String> userIDs = new ArrayList<String>();
		boolean allusers = false;
		if(statWhom.equals("personal")){
			userIDs.add(currentUser.getUserID());
		}
		else {
			userIDs = null;
			allusers = true;
		}

		Calendar startDate = Calendar.getInstance();
		Calendar stopDate  = Calendar.getInstance();
		StatisticsDateType dateType = null;
		if(statTime.equals("week")) {
			startDate.setFirstDayOfWeek(Calendar.MONDAY);
			startDate.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
			startDate.add(Calendar.DAY_OF_MONTH, -(startDate.get(startDate.DAY_OF_WEEK) - startDate.MONDAY));
			startDate.set(Calendar.HOUR,0);
			startDate.set(Calendar.MINUTE,0);
			stopDate.setFirstDayOfWeek(Calendar.MONDAY);
			stopDate.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
			stopDate.add(Calendar.DAY_OF_MONTH, -(stopDate.get(stopDate.DAY_OF_WEEK) - stopDate.SUNDAY));
			startDate.add(Calendar.WEEK_OF_YEAR, -statOffs);
			stopDate.add(Calendar.WEEK_OF_YEAR, -statOffs);
			dateType = StatisticsDateType.DAILY;
		}
		else if(statTime.equals("month")) {
			startDate.set(Calendar.DAY_OF_MONTH, 1);
			stopDate.set(Calendar.DAY_OF_MONTH, 31);
			startDate.add(Calendar.MONTH, -statOffs);
			stopDate.add(Calendar.MONTH, -statOffs);
			dateType = StatisticsDateType.WEEKLY;
		}
		else if(statTime.equals("semester")) {
			if(statOffs == 1)
				startDate.set(Calendar.MONTH, 8);
			if(startDate.get(Calendar.MONTH) <= 7){
				startDate.set(Calendar.MONTH, 1);
				stopDate.set(Calendar.MONTH, 8);
				stopDate.add(Calendar.YEAR , 1);
			}
			else{
				startDate.set(Calendar.MONTH, 8);
				stopDate.set(Calendar.MONTH, 1);
				stopDate.add(Calendar.YEAR, 1);
			}
			dateType = StatisticsDateType.MONTHLY;
			
		}
		
		String charttype = null;
		ArrayList cd = new ArrayList();
		
		if (statChar.equals("chart_pie")){
			if(statType.equals("time_spent")) {
				charttype = "types";
				
				cd.add(new ColumnDescription("act_type", ValueType.TEXT, "Activity Type"));
				cd.add(new ColumnDescription("time", ValueType.NUMBER, "Time spend"));
			}
			else if(statType.equals("time_courses")) {
				charttype = "courses";
				
				cd.add(new ColumnDescription("course", ValueType.TEXT, "Course"));
				cd.add(new ColumnDescription("time", ValueType.NUMBER, "Time spend"));
			} 
			else if(statType.equals("time_spare")) {
				charttype = "spare_time";
				
				cd.add(new ColumnDescription("spare_time", ValueType.TEXT, "Spare Time Type"));
				cd.add(new ColumnDescription("time", ValueType.NUMBER, "Time spend"));
			} 
			else if(statType.equals("prod_total")) {
				
			} 
			else if(statType.equals("prod_course")) {
				
			} 
			else if(statType.equals("stat_time_spend")) {
					
			} 
			
			Map<String, Long> stat = statisticsManager.statTimeSpend(userIDs, allusers,charttype,startDate.getTime(),stopDate.getTime());

			System.out.println(""+userIDs + allusers+charttype+startDate.getTime()+stopDate.getTime());
			
			try {
				data.addColumns(cd);
				for(String type : stat.keySet()) {
					data.addRowFromValues(type, stat.get(type));
				}
			}
			catch (TypeMismatchException e) {
				System.out.println(" - Invalid type!");
			}
		}
		else {
			boolean emptyGraph = true;
			if(statType.equals("time_spent")) {
				charttype = "types";

				cd.add(new ColumnDescription("day", ValueType.TEXT, "Day"));
				cd.add(new ColumnDescription("time_study", ValueType.NUMBER, "Time studied"));
				cd.add(new ColumnDescription("time_class", ValueType.NUMBER, "Time in class"));
				cd.add(new ColumnDescription("time_spare", ValueType.NUMBER, "Spare Time"));
				
				Map<String, LinkedHashMap<String, Long>> stat = statisticsManager.statTimeSpentBar(userIDs, allusers,charttype,dateType,startDate.getTime(),stopDate.getTime());
				
				try {
					data.addColumns(cd);
					for(String type : stat.keySet()) {
						if (stat.get(type).size() != 0 )
							emptyGraph = false;
						data.addRowFromValues(type, stat.get(type).get("STUDY"), stat.get(type).get("LESSON"), stat.get(type).get("SPARE_TIME"));
					}
				}
				catch (TypeMismatchException e) {
					System.out.println(" - Invalid type!");
				}
			}
			else if(statType.equals("time_courses")) {
				//alleen totaal in pie tot nu toe
				charttype = "courses";
				String course = courseManager.getCourseByID(statCrse).getName(); // get coursename
				cd.add(new ColumnDescription(course, ValueType.TEXT, "Course"));
				cd.add(new ColumnDescription("time", ValueType.NUMBER, "Time spend on " + course));
				// -
				
				
				Map<String, LinkedHashMap<String, Long>> stat = statisticsManager.statTimeSpentBar(userIDs, allusers,charttype,dateType,startDate.getTime(),stopDate.getTime());
				
				try {
					data.addColumns(cd);
					for(String type : stat.keySet()) {
						if (stat.get(type).containsKey(course))
							emptyGraph = false;
						data.addRowFromValues(type, stat.get(type).get(course));
					}
				}
				catch (TypeMismatchException e) {
					System.out.println(" - Invalid type!");
				}
			} 
			
			else if(statType.equals("time_spare")) {
				charttype = "spare_time";
				
				
				cd.add(new ColumnDescription("day", ValueType.TEXT, "Day"));
				cd.add(new ColumnDescription("EAT", ValueType.NUMBER, "Eating"));
				cd.add(new ColumnDescription("SPORT", ValueType.NUMBER, "Sport"));
				cd.add(new ColumnDescription("SLEEP", ValueType.NUMBER, "Sleep"));
				cd.add(new ColumnDescription("PARTY", ValueType.NUMBER, "Party"));
				cd.add(new ColumnDescription("HOBBY", ValueType.NUMBER, "Hobby"));
				
				Map<String, LinkedHashMap<String, Long>> stat = statisticsManager.statTimeSpentBar(userIDs, allusers,charttype,dateType,startDate.getTime(),stopDate.getTime());
				
				try {
					data.addColumns(cd);
					for(String type : stat.keySet()) {
						if (stat.get(type).size() != 0 )
							emptyGraph = false;
						data.addRowFromValues(type, stat.get(type).get("EAT"),stat.get(type).get("SPORT"),stat.get(type).get("SLEEP"),stat.get(type).get("PARTY"),stat.get(type).get("HOBBY"));
					}
				}
				catch (TypeMismatchException e) {
					System.out.println(" - Invalid type!");
				}
			} 
			
			
			else if(statType.equals("prod_total")) {
				
				cd.add(new ColumnDescription("day", ValueType.TEXT, "Day"));
				cd.add(new ColumnDescription("time_study", ValueType.NUMBER, "Productivity total"));
				ArrayList<Integer> questionIDs = new ArrayList<Integer>();
				questionIDs=questionManager.getQuestionIDMap().get("Productiviteit");
				
				Map<String, Long> stat = statisticsManager.statQuestions(userIDs, allusers,startDate.getTime(),stopDate.getTime(), questionIDs,dateType,"");
				
				try {
					data.addColumns(cd);
					for(String type : stat.keySet()) {
						if (stat.get(type) != 0 )
							emptyGraph = false;
						data.addRowFromValues(type,stat.get(type));
					}
				}
				catch (TypeMismatchException e) {
					System.out.println(" - Invalid type!");
				}


			} 
			else if(statType.equals("prod_course")) {
				
			} 
			else if(statType.equals("stat_time_spend")) {
				
			}
			if(emptyGraph){
				data=new DataTable();
			    data.addColumns(cd);
			}
		}
		
		
		
		
		
		
		/*if(statType.equals("stat_time_spend")) {
			List<String> onlyCurrentUser = new ArrayList<String>();
			onlyCurrentUser.add(currentUser.getUserID());
			Map<String, Long> stat = statisticsManager.statTimeSpend(onlyCurrentUser, false, "types_pie_chart",startDate.getTime(),stopDate.getTime());
			
			
			ArrayList cd = new ArrayList();
			cd.add(new ColumnDescription("act_type", ValueType.TEXT, "Activity Type"));
			cd.add(new ColumnDescription("time", ValueType.NUMBER, "Time spend"));
			data.addColumns(cd);

			try {
				for(String type : stat.keySet()) {
					data.addRowFromValues(type, stat.get(type));
				}
			}
			catch (TypeMismatchException e) {
				System.out.println(" - Invalid type!");
			}
		}
		
		if(statType.equals("highscores_points")) {
			HashMap<Integer,User> pointsMap = new HashMap<Integer,User>();
			List<Entity> userList = userManager.getAllUsers();

			for(Entity userentity: userList)
			{
				String ID = (String) userentity.getProperty("UserID");
				User user = userManager.getUser(ID);
				Integer points = user.getPoints();
				pointsMap.put(points,user);
				
			}

			TreeMap<Integer,User> sortedPointsMap = new TreeMap<Integer, User>(pointsMap);
			Object[] mapUsers = sortedPointsMap.values().toArray();
			Object[] mapIntegers = sortedPointsMap.keySet().toArray();

	
			ArrayList<ColumnDescription> cd = new ArrayList<ColumnDescription>();
			cd.add(new ColumnDescription("User", ValueType.TEXT, "The user"));
			cd.add(new ColumnDescription("Points", ValueType.NUMBER, "Total points"));
			
			data.addColumns(cd);
			Integer teller = mapIntegers.length-1;
			while(teller+1>0)
			{
				data.addRowFromValues( ((User) mapUsers[teller]).getName(),mapIntegers[teller]);
				teller--;
			}
			return data;
			
		}
		
		else if(statType.equals("blabla")) {
			
			ArrayList cd = new ArrayList();
			cd.add(new ColumnDescription("day", ValueType.TEXT, "Day in the week"));
			cd.add(new ColumnDescription("study", ValueType.NUMBER, "Hours studied"));
			cd.add(new ColumnDescription("class", ValueType.NUMBER, "Hours in class"));
			cd.add(new ColumnDescription("other", ValueType.NUMBER, "Hours spend on spare time"));
			
			data.addColumns(cd);
			System.out.println(" - Data: "+data);
			
			// Fill the data table.
			try {
				data.addRowFromValues("Monday", 0, 8, 0);
				data.addRowFromValues("Tuesday", 1, 8, 0);
				data.addRowFromValues("Wednesday", 4, 0, 3);
				data.addRowFromValues("Thursday", 2, 7, 1);
				data.addRowFromValues("Friday", 0, 4, 5);
				data.addRowFromValues("Saturday", 5, 10, 7);
				data.addRowFromValues("Sunday", 6, 10, 7);
				System.out.println(" - Data: "+data);
			}
			catch (TypeMismatchException e) {
				System.out.println("Invalid type!");
			}
		}*/
		
				
		return data;
	}

}